package com.gitee.fsmxm.ocon.util;

import com.gitee.fsmxm.ocon.model.Task;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author fsmxm
 */
public class WinTaskUtils {

    private WinTaskUtils() {
    }

    private static final String TASK_KILL = "TASKKILL";
    private static final String TASK_LIST = "TASKLIST";

    /**
     * 强制杀死进程
     *
     * @param imageName 指定进程名称
     * @return 结果
     * @throws IOException io e
     */
    public static String[] forceKillAll(String imageName) throws IOException {
        return execute(Arrays.asList(TASK_KILL, "/IM", imageName, "/F", "/T"));
    }

    /**
     * 强制杀死进程
     *
     * @param pid pid
     * @return 结果
     * @throws IOException io e
     */
    public static String[] forceKillAll(int pid) throws IOException {
        return execute(Arrays.asList(TASK_KILL, "/PID", pid + "", "/F", "/T"));
    }

    /**
     * 获取进程，根据指定进程id
     *
     * @param pid pid
     * @return task
     * @throws IOException ioe
     */
    public static Task getTask(int pid) throws IOException {
        List<String> commands = new ArrayList<>(6);
        commands.add(TASK_LIST);
        commands.add("/FO");
        commands.add("CSV");
        commands.add("/NH");
        commands.add("/FI");
        commands.add("\"PID eq " + pid + "\"");
        final String[] result = execute(commands);
        if (result[0].isEmpty()) {
            return null;
        }
        final String[] segs = result[0].split(",");
        // 处理没查询到匹配的进程信息，出现返回这种消息“信息: 没有运行的任务匹配指定标准。”的情况
        if (segs.length < 4) {
            return null;
        }
        Task task = new Task();
        task.setImageName(segs[0].substring(1, segs[0].length() - 1));
        task.setPid(Integer.parseInt(segs[1].substring(1, segs[1].length() - 1)));
        task.setSessionName(segs[2].substring(1, segs[2].length() - 1));
        task.setSession(Integer.parseInt(segs[3].substring(1, segs[3].length() - 1)));
        return task;
    }

    public static List<Task> listTask(String imageName) throws IOException {
        return listTask(imageName, null);
    }

    /**
     * 获取进程列表
     *
     * @param imageName 指定进程名称
     * @return task list
     * @throws IOException io e
     */
    public static List<Task> listTask(String imageName, int[] excludePid) throws IOException {
        List<String> commands = new ArrayList<>(8);
        commands.add(TASK_LIST);
        commands.add("/FO");
        commands.add("CSV");
        commands.add("/NH");
        commands.add("/FI");
        commands.add("\"IMAGENAME eq " + imageName + "\"");
        if (excludePid != null) {
            for (int pid : excludePid) {
                commands.add("/FI");
                commands.add("\"PID ne " + pid + "\"");
            }
        }
        final String[] result = execute(commands);
        List<Task> tasks = new ArrayList<>(8);
        if (!result[0].isEmpty()) {
            final String[] split = result[0].split("\n");
            for (String sp : split) {
                final String[] segs = sp.split(",");
                // 处理没查询到匹配的进程信息，出现返回这种消息“信息: 没有运行的任务匹配指定标准。”的情况
                if (segs.length < 4) {
                    continue;
                }
                Task task = new Task();
                task.setImageName(segs[0].substring(1, segs[0].length() - 1));
                task.setPid(Integer.parseInt(segs[1].substring(1, segs[1].length() - 1)));
                task.setSessionName(segs[2].substring(1, segs[2].length() - 1));
                task.setSession(Integer.parseInt(segs[3].substring(1, segs[3].length() - 1)));
                tasks.add(task);
            }
        }
        return tasks;
    }

    private static String[] execute(List<String> commands) throws IOException {
        ProcessBuilder processBuilder = new ProcessBuilder(commands);
        Process process = processBuilder.start();

        String[] result = new String[2];
        try (InputStream inputStream = process.getInputStream()) {
            result[0] = IOUtils.toString(inputStream, "GBK");
        }

        try (InputStream inputStream = process.getErrorStream()) {
            result[1] = IOUtils.toString(inputStream, "GBK");
        }
        return result;
    }

    // String commands[] = new String[] {"CSCRIPT", "/Nologo", "aaa.vbs", "5600"};

}
